﻿using System;
using System.Data;
using System.Collections.Generic;

using BizElements.BusinessLayer;

namespace BizElements.Web
{
    /// <summary>
    /// Generic component that displays search results and provides custom actions for selected items.
    /// </summary>
    /// <remarks>Commonly used in pair with a <see cref="ISearchFilter"/> component.</remarks>
    public interface ISearchView
    {
        #region Methods.

        /// <summary>
        /// Searches for data that matches the engine's filter criteria and displays results.
        /// </summary>
        /// <returns>Data returned by the <see cref="Engine"/>.</returns>
        DataView Search();

        /// <summary>
        /// Returns data fetched by the <see cref="Engine"/>.
        /// </summary>
        /// <returns>Data returned by the <see cref="Engine"/>.</returns>
        DataView GetData();

        /// <summary>
        /// Gets <see cref="ISearchView"/> settings.
        /// </summary>
        /// <returns>A collection of key-value property pairs guaranteed to work only with 
        /// the <see cref="ISearchView"/> implementation which created it.</returns>
        IDictionary<string, object> GetSettings();

        /// <summary>
        /// Applies <see cref="ISearchView"/> settings to the current instance.
        /// </summary>
        /// <param name="properties">Settings collection which was created by the same or compatibile
        /// <see cref="ISearchView"/> implementation as the current instance.</param>
        void ApplySettings(IDictionary<string, object> properties);

        #endregion

        #region Properties.

        /// <summary>
        /// Gets or sets the underlying search engine which contains meta-data and accesses the data-source.
        /// </summary>
        ISearchEngine Engine { get; set; }

        /// <summary>
        /// Gets or sets the actor using the component. Nullable.
        /// </summary>
        /// <remarks>When set the component should run security checks to see which of the commands 
        /// provided in the <see cref="Commands"/> list the actor is allowed to execute.</remarks>
        IActor Actor { get; set; }

        /// <summary>
        /// Gets or sets the value indicating whether the component may cache data 
        /// or whether it has to access data-source every time it needs to display data.
        /// </summary>
        bool CacheEnabled { get; set; }

        /// <summary>
        /// Gets or sets the values indicating whether the <see cref="Search"/> method will count all records matching the filter criteria. 
        /// </summary>
        /// <remarks>Total count may be greater than the number of retrieved records if <see cref="MaxRecordCount"/> property is set.</remarks>
        bool CountAllRecords { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="IMessageFormatter"/> object used to format values.
        /// </summary>
        IMessageFormatter Formatter { get; set; }

        /// <summary>
        /// Gets or sets the maximum number of records to retrieve from the data-source.
        /// </summary>
        int MaxRecordCount { get; set; }

        /// <summary>
        /// Gets or sets the value indicating whether multiple rows can be selected.
        /// </summary>
        bool MultiRowSelect { get; set; }

        /// <summary>
        /// Gets or sets the format of the message which displays the total count of records matching the filter criteria.
        /// </summary>
        /// <remarks>Message is displayed only if <see cref="CountAllRecords"/> property is set to <b>true</b>.</remarks>
        string RecordCountFormat { get; set; }

        /// <summary>
        /// Gets or sets a collection of <see cref="ICommand"/> objects that work with the retrieved data.
        /// </summary>
        IList<ICommand> Commands { get; set; }

        #endregion

        #region Sorting.

        /// <summary>
        /// Gets or sets the value indicating whether sorting operations will take place on the data-source 
        /// or in the ISearchView component after the data has been fetched.
        /// </summary>
        /// <remarks>Performance is generally better when sorting in the ISearchView component.
        /// This is because the component is not sorting all records in the data-source but only
        /// the top <see cref="MaxRecordCount"/> ones retrieved from the data-source. The resultset
        /// may differ from the one that would be returned from the data-source if this value 
        /// was set to <b>true</b>.</remarks>
        bool SortInDataSource { get; set; }

        /// <summary>
        /// Gets whether the view supports sorting.
        /// </summary>
        bool SupportsSorting { get; }

        /// <summary>
        /// Gets or sets a value that indicates whether sorting is enabled. 
        /// </summary>
        bool AllowSorting { get; set; }

        /// <summary>
        /// Sorts view data.
        /// </summary>
        /// <param name="field">Field whose values are to be sorted.</param>
        /// <param name="ascending">Specifies whether the values in the specified field 
        /// should be sorted in ascending order, from lowest value to highest value.</param>
        void Sort(string field, bool ascending);

        /// <summary>
        /// Reverses current sort direction. No affect if data is currently not sorted.
        /// </summary>
        void ReverseSort();

        /// <summary>
        /// Removes current sort order applied to data.
        /// </summary>
        void RemoveSort();

        #endregion

        #region Paging.

        /// <summary>
        /// Gets whether the view supports paging.
        /// </summary>
        bool SupportsPaging { get; }

        /// <summary>
        /// Gets or sets a value that indicates whether paging is enabled.
        /// </summary>
        bool AllowPaging { get; set; }

        /// <summary>
        /// Gets or sets the index of the currently displayed page. 
        /// </summary>
        int CurrentPageIndex { get; set; }

        /// <summary>
        /// Gets the total number of pages.
        /// </summary>
        int PageCount { get; }

        /// <summary>
        /// Gets or sets the number of items on a single page of the view. 
        /// </summary>
        int PageSize { get; set; }

        #endregion

        #region Events.

        /// <summary>
        /// Occurs when the selected command cannot be executed.
        /// </summary>
        event EventHandler<BusinessRuleEventArgs> CommandGrantExecuteFailed;

        #endregion
    }
}